import utils
import re
import json
import codecs
import requests
from login import OneClickLogin, use_default_login
from urllib3.exceptions import InsecureRequestWarning

# 禁用安全请求警告
requests.urllib3.disable_warnings(InsecureRequestWarning)

class WeChatClient:
    def __init__(self, login_service, url='https://mp.weixin.qq.com'):
        """
        通过moka登录接口获取公众号后台资料
        :param OneClickLogin login_service:
        """
        self.url = url
        self.login = login_service
        self.session = utils.requests_retry_session()
        self.gh_id = None
        self.gh_nickname = None
        self.token = None
        self.index_url = None
        self.index_response = None
        self.violation_list = []

    def log_line(self, msg, gh_nickname=None, gh_id=None):
        line = '[{}]({}) {}'.format(gh_nickname if gh_nickname else self.gh_nickname,
                                    gh_id if gh_id else self.gh_id, msg)
        print(line)
        return line

    def log_err(self, err, logtype='log', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)

    def debug_log(self, err, logtype='debug', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)
        print(err)

    def detect_account_type(self):
        m = re.search(r'>((订阅|服务)号)</a>', self.index_response, re.MULTILINE)
        if m:
            return m.group(1)

    def enter(self, gh_id, gh_nickname):
        cookies = self.login.get_wx_cookie(gh_id)
        if cookies:
            self.log_line('获取Cookie成功', gh_nickname, gh_id)
            utils.set_cookies(self.session, cookies)
        else:
            try:
                self.log_line('一键登录状态异常', gh_nickname=gh_nickname, gh_id=gh_id)
                dict_read = {
                    "nickname": gh_nickname,
                    "gh_id" : gh_id,
                    "nan": "{0}".format(""),
                    "nv": "{0}".format(""),
                    "unknown": "{0}".format("一键登录异常")
                }
                with codecs.open('fans_number.json', 'a', 'utf-8') as f:
                    f.write(json.dumps(dict_read) + "\r")
                return False
            except Exception as e:
                print(e)
                return False
        try:
            response = self.session.get(url=self.url, verify=False)
            self.index_url = str(response.url)
            try:
                token = re.findall('token=(\\d+)', self.index_url)[0]
            except IndexError:
                self.log_err('微信后台登录失败，检查Cookie是否有效',
                             gh_nickname=gh_nickname, gh_id=gh_id)
                return False
            self.gh_id = gh_id
            self.gh_nickname = gh_nickname
            self.token = token
            self.index_response = response.content.decode('utf-8')
            self.log_line('后台登录成功，Token={}'.format(token))
            return True
        except Exception as e:
            print(e)
            return False

    def save_data(self, data_file, data_date, data):
        with utils.open_write_data_file(self.gh_id, data_file, data_date) as f:
            json.dump(data, f)

    def detect_or_save(self, data_file, data_name, data_date, func, skip_exist=True, verbose=True):
        if skip_exist and utils.has_data_file(self.gh_id, data_file, data_date):
            if verbose:
                self.log_line('已存在{}，跳过'.format(data_name))
        else:
            if verbose:
                self.log_line('开始获取{}'.format(data_name))
            data = func(data_date)
            if data:
                if verbose:
                    self.log_line('获取{}成功'.format(data_name))
                self.save_data(data_file, data_date, data)
            else:
                self.log_err('获取{}失败,请重试,或单独爬取'.format(data_name))

    def save_basic_info(self, account, date):
        self.save_data('basic.json', date, account)

    def save_sexs_infos(self, date):
        resp = self.session.get(
            '{0}/misc/useranalysis?action=attr&begin_date={1}&end_date={1}&token={2}&lang=zh_CN&f=json&ajax=1'.format(
                self.url, date, self.token), verify=False)
        try:
            data = resp.json()
            if data['load_done'] and data['user_portrait']['list']:
                line = data['user_portrait']['list'][0]
                if len(line["genders"]) == 3:
                    unknown = line["genders"][2]["user_count"]
                    if line["genders"][0]["attr_value"] == "1":
                        nan = line["genders"][0]["user_count"]
                        nv = line["genders"][1]["user_count"]
                    else:
                        nv = line["genders"][0]["user_count"]
                        nan = line["genders"][1]["user_count"]
                else:
                    unknown = ""
                    if line["genders"][0]["attr_value"] == "1":
                        nan = line["genders"][0]["user_count"]
                        nv = line["genders"][1]["user_count"]
                    else:
                        nv = line["genders"][0]["user_count"]
                        nan = line["genders"][1]["user_count"]
                return nan, nv, unknown
            else:
                self.log_err("微信后台没有数据")
                return "", "", ""
        except (KeyError, ValueError, TypeError, IndexError):
            self.debug_log(resp.content)
            return "", "", ""


def collect(login_service, account, data_date=None):
    if not data_date:
        data_date = utils.get_yesterday()
    srv = WeChatClient(login_service)
    if not srv.enter(account['gh_id'], account['nickname']):
        return
    account_type = srv.detect_account_type()
    if account_type:
        srv.log_line(account_type)
        account['type'] = account_type
    srv.save_basic_info(account, data_date)
    nan, nv, unknown= srv.save_sexs_infos(data_date)
    info = {
        "nickname" : account['nickname'],
        "gh_id" : account['gh_id'],
        "nan" : nan,
        "nv" : nv,
        "unknown" : unknown
    }
    with codecs.open('fans_number.json','a','utf-8') as f:
        f.write(json.dumps(info) +"\r")


def test_collect(date):
    library = utils.default_library()
    account_list = library.get_account_list()
    if account_list:
        login_srv = use_default_login()
        for gh_id in account_list:
            account = library.get_account_data(gh_id)
            collect(login_srv, account, date)
    else:
        print('账号列表为空，退出')